package edu.cmu.arch.pipesandfilters;

import java.io.IOException;

import edu.cmu.arch.pipesandfilters.frame.Frame;
import edu.cmu.arch.pipesandfilters.frame.Variable;

/**
 * The ConversionFilter class serves the purpose of performing conversions
 * for two different types (temperature and altitude). Temperature will be 
 * converted from fahrenheit to celsius. Altitude will be converted from 
 * feet to meters.
 * 
 * To use this class, an instance of it must be instantiated with the type of 
 * measurement that needs to be converted.
 * 
 * @author Brian Laick (blaick@andrew.cmu.edu)
 */
public class ConversionFilter extends FrameFilterFramework 
{
	private Variable conversionType = null;
	
	/*
	 * Constructor for the class. Sets the measurement type to be converted.
	 * @param Variable measurement type to be converted.
	 */
	public ConversionFilter (Variable conversionRequested)
	{
		conversionType = conversionRequested;
	}
	
	/**
	 * Overridden method. Starts the ConversionFilter
	 * 
	 * (non-Javadoc)
	 * @see edu.cmu.arch.pipesandfilters.FilterFramework#run()
	 */
	public void run() 
	{	
		System.out.print("\n" + this.getName() + "::ConversionFilter Reading");
		Frame frame = null;
		
		try
		{
			while(true) 
			{
				// Read values off the stream
				frame = this.readFrame();
				
				if(conversionType == Variable.Temperature)
				{
					temperatureConversion(frame);
				}
				else if (conversionType == Variable.Altitude)
				{
					altitudeConversion(frame);
				}
				else
				{
					System.out.println("Variable specified is not supported.");
				}
				writeFrame(frame);
			}
		} catch (EndOfStreamException eose) {
			// Not an error, stream is ended.
		} catch (IOException e) {
			System.out.println(this.getName() + "::run() IOException occured" + e.getMessage());
		}
	}

	private void temperatureConversion(Frame frame) 
	{
		// Get temperature value in Fahrenheit
		double fahrenheitTemp = frame.getValue(Variable.Temperature).doubleValue();
		
		// Convert
		double celsiusTemp = convertFahrenheitToCelsius(fahrenheitTemp); 
		
		// Write out new celsius value to stream
		frame.putValue(Variable.Temperature, celsiusTemp);
	}
	
	private void altitudeConversion(Frame frame)
	{
		// Get altitude value in feet
		double altitudeFt = frame.getValue(Variable.Altitude).doubleValue();

		// Convert
		double altitudeMeters = convertFeetToMeters(altitudeFt);
		
		// Write out new altitude in meters
		frame.putValue(Variable.Altitude, altitudeMeters);
	}

	private double convertFahrenheitToCelsius(double fahrenheitTemp) 
	{
		return (fahrenheitTemp- 32)/ 1.8;
	}
	
	private double convertFeetToMeters(double altitudeInFeet)
	{
		return altitudeInFeet * 0.3048;
	}
}
